// 1、compose函数

// function fn1(x) {
// 	return x + 1
// }
// function fn2(x) {
// 	return x + 2
// }
// function fn3(x) {
// 	return x + 3
// }
// function fn4(x) {
// 	return x + 4
// }
// function compose(...arg) {
// 	let arr = arg
// 	return arr.reduce((prev, next) => {
// 		return (num) => {
// 			return prev(next(num))
// 		}
// 	})
// }
// let a = compose(fn1, fn2, fn3, fn4)
// console.log(a(1))


// 2、setTimeout模拟实现setInterval

// function test() {
// 	console.log('3333333')
// }
// function mySetInterval(fn, delay = 1000) {
// 	let timer = null
// 	let interval = () => {
// 		fn()
// 		if(timer) clearTimeout(timer)
// 		timer = setTimeout(interval, delay)
// 	}
// 	timer = setTimeout(interval, delay)
// 	return {
// 		cancle: () => clearTimeout(timer)
// 	}
// }
// mySetInterval(test)


// 3、setInterval模拟实现setTimeout


// function test() {
// 	console.log('3333333333')
// }

// function mySetTimeout(fn, delay = 1000) {
// 	let timer = null
// 	timer = setInterval(() => {
// 		clearInterval(timer)
// 		fn()
		
// 	}, delay)
// }
// mySetTimeout(test)


// 实现发布订阅模式

// class EventEmitter{
// 	constructor() {
// 		this.cache = {}
// 	}

// 	on(type, fn) {
// 		if(!this.cache[type]) this.cache[type] = []
// 		this.cache[type].push(fn)
// 	}

// 	off(type, fn) {
// 		if(!this.cache[type]) return
// 		if(!fn) {
// 			this.cache[type] = []
// 		}else {
// 			this.cache[type] = this.cache[type].filter(item => item !== fn)
// 		}  
// 	}

// 	emit(type, ...arg) {
// 		if(!this.cache[type]) return
// 		this.cache[type].forEach(item => item(...arg))
// 	}

// 	once(type, fn) {
// 		const fnNew = () => {
// 			fn()
// 			this.off(type, fnNew)
// 		}
// 		this.on(type, fnNew)
// 	}
// }

// 5、数组去重

// function uniqueArr(arr) {
// 	return [...new Set(arr)]
// }

// console.log(uniqueArr([1,2,3,5,5,6,6]))


// 6、数组扁平化

// const isHasArr = (arr) => arr.some(item => Array.isArray(item))

// function flatter(arr, count) {
// 	let i = 0
// 	while(isHasArr(arr) && (!count || i < count)) {
// 		arr = [].concat(...arr)
// 		i++
// 	}	
// 	return arr
// }
// console.log(flatter([1,2,3,[1,2,[2, [5]]]]))


// 7、寄生组合式继承

// function Parent(name) {
// 	this.name = name
// 	this.say = function () {
// 		console.log(`我是${this.name}, 今年${this.age}岁`)
// 	}
// }

// function Child(name, age) {
// 	Parent.call(this, name)
// 	this.age = age
// }

// Child.prototype = Object.create(Parent.prototype)

// Child.prototype.constructor = Child

// const child = new Child('张三', 18)

// child.say()


// 8、实现一个promise调度器

// class Scheduler{
// 	constructor(limit) {
// 		this.limit = limit
// 		this.taskQueue = []
// 		this.startTaskCount = 0
// 	}

// 	add(time, info) {
// 		const fn = () => {
// 			return new Promise((rsolve, reject) => {
// 				setTimeout(() => {
// 					console.log(info)
// 					rsolve()
// 				}, time)
// 			}) 
// 		}
// 		this.taskQueue.push(fn)
// 	}

// 	startTask() {
// 		for(let i = 0; i < this.limit; i++) {
// 			this.request()
// 		}
// 	}

// 	request() {
// 		if(this.startTaskCount >= this.limit || this.taskQueue.length < 1) return
// 		this.startTaskCount++
// 		this.taskQueue.shift()().then(() => {
// 			this.startTaskCount--
// 			this.request()
// 		})
// 	}
// }

// const scheduler = new Scheduler(2)
// scheduler.add(1000, "1")
// scheduler.add(500, "2")
// scheduler.add(300, "3")
// scheduler.add(400, "4")
// scheduler.startTask()


// 9、实现new操作符

// function myNew(Fn, ...arg) {
// 	let obj = Object.create(null)
// 	obj.__proto__ = Fn.prototype
// 	let result = Fn.call(obj, ...arg)
// 	return (typeof result === 'object' && result !== null) || typeof result === 'function' ? result : obj
// }


// 10、深拷贝

// function deepClone(obj) {
// 	if(typeof obj !== 'object' || obj === null) {
// 		return obj
// 	}else if(obj instanceof Set) {
// 		let set = new Set()
// 		obj.forEach(item => {
// 			set.add(deepClone(item))
// 		})
// 		return set
// 	}else if(obj instanceof Map) {
// 		let map = new Map()
// 		obj.forEach((item, key) => {
// 			map.set(key, deepClone(item))
// 		})
// 		return map
// 	}else if(obj instanceof RegExp) {
// 		return new RegExp(obj)
// 	}else if(obj instanceof Date) {
// 		return new Date(obj)
// 	}else {
// 		let cloneObj = Array.isArray(obj) ? [] : {}4
// 		for(let key in obj) {
// 			if(obj.hasOwnProperty(key)) {
// 				cloneObj[key] = deepClone(obj[key])
// 			}
// 		}
// 		return cloneObj
// 	}
// }

// 11、instanceof

// function myInstanceof(child, parent) {
// 	while(child) {
// 		if(child.__proto__ === parent.prototype) return true
// 		child = child.__proto__
// 	}
// 	return false
// }

// function Test() {}
// let test = new Test()

// console.log(myInstanceof(test, Test))


// 12、函数柯里化
// function fn(a, b, c, d) {
// 	return a + b + c + d
// }

// function currying(fn, ...arg) {
// 	let args = [...arg]
// 	const result = (...Arg) => {
// 		args = [...args, ...Arg]
// 		if(args.length >= fn.length) {
// 			return fn(...args)
// 		}
// 		return result
// 	}
// 	return result
// }

// let fn1 = currying(fn, 1,2)
// console.log(fn1(3,5, 7))



// 13、实现LanMan函数

// function LazyMan(name) {
// 	return new _LazyMan(name)
// }

// class _LazyMan{
// 	constructor(name) {
// 		this.name = name
// 		this.taskQueue = []
// 		const fn = () => {
// 			console.log(`Hi! This is ${this.name}`)
// 			this.next()
// 		}
// 		this.taskQueue.push(fn)
// 		Promise.resolve().then(() => {
// 			this.next()
// 		})
// 	}

// 	next() {
// 		if(!this.taskQueue.length) return
// 		this.taskQueue.shift()()
// 	}

// 	eat(food) {
// 		const fn = () => {
// 			console.log(`Eat ${food}~`)
// 			this.next()
// 		}
// 		this.taskQueue.push(fn)
// 		return this
// 	}

// 	sleep(s) {
// 		this.timeFn(10, true)
// 		return this
// 	}

// 	sleepFirst(s) {
// 		this.timeFn(5, false)
// 		return this
// 	}

// 	timeFn(s, flag) {
// 		const fn = () => {
// 			setTimeout(() => {
// 				console.log(`Wake Up after ${s}秒`)
// 				this.next()
// 			}, s*1000)
// 		}
// 		if(flag) {
// 			this.taskQueue.push(fn)
// 		}else {
// 			this.taskQueue.unshift(fn)
// 		}
// 	}


// }

// // LazyMan('Hank')
// // Hi! This is Hank!

// // LazyMan('Hank').sleep(10).eat('dinner')
// // Hi! This is Hank!
// //等待10秒..
// // Wake up after 10
// // Eat dinner~

// // LazyMan('Hank').eat('dinner').eat('supper')
// // Hi This is Hank!
// // Eat dinner~
// // Eat supper~

// // LazyMan('Hank').eat('supper').sleepFirst(5)
// //等待5秒
// // Wake up after 5
// // Hi This is Hank!
// // Eat supper


// 14、版本排序的方法

// function MySort(arr) {
// 	arr.sort((a, b) => {
// 		let i = 0
// 		let arr1 = a.split('.')
// 		let arr2 = b.split('.')
// 		while(true) {
// 			let s1 = arr1[i]
// 			let s2 = arr2[i]
// 			i++

// 			if(s1 === undefined || s2 === undefined) return arr2.length - arr1.length	
// 			if(s1 === s2) continue

// 			return s2 - s1
// 		}
// 	})
// 	return arr
// }

// console.log(MySort(['0.1.1', '2.3.3', '0.302.1', '4.2', '4.3.5', '4.3.4.5']))

// 15、LRUCache函数

// class LRUCache{
// 	constructor(limit) {
// 		this.limit = limit
// 		this.map = new Map()
// 	}

// 	get(key) {
// 		if(!this.map.has(key)) return -1
// 		let tempValue = this.map.get(key)
// 		this.map.delete(key)
// 		this.map.set(key, tempValue)

// 		return tempValue
// 	}

// 	put(key, value) {
// 		if(this.map.has(key)) {
// 			this.map.delete(key)
// 			this.map.set(key, value)
// 		}else {
// 			if(this.map.size === this.limit) {
// 				this.map.delete(this.map.keys().next().value)
// 				this.map.set(key, value)
// 			}else {
// 				this.map.set(key, value)
// 			}
// 		}
// 	}
// }


// 16、add函数

// function add(...arg) {
// 	let args = [...arg]
// 	const fn = (...Arg) => {
// 		args = [...args, ...Arg]
// 		return fn
// 	}

// 	fn.toString = () => {
// 		if(!args.length) return
// 		return args.reduce((prev, curr) => prev + curr, 0)
// 	}

// 	return fn
// }

// console.log(add(1,2,3)(4)()==10)

// 17、动态规划求解硬币找零

// function coinChange(coins, amount) {
// 	if(coins.length < 1) return -1
// 	let dp = []
// 	dp[0] = 0
// 	let len = coins.length
// 	for(let i = 1; i <= amount; i++){
// 			dp[i] = Infinity
// 			for(let j = 0; j < len; j++) {
// 				 if(i >= coins[j]) {
// 							dp[i] = Math.min(dp[i], dp[i - coins[j]] + 1)
// 				 }
// 			}
// 	}
// 	if(dp[amount] === Infinity) return -1
// 	return dp[amount]
// };

// console.log(coinChange([1, 2, 5], 11))

// 18、请实现DOM2JSON一个函数，可以把一个DOM节点输出JSON格式

// function dom2Json(domtree) {
// 	let obj = {}
// 	obj.name = domtree.tagName
// 	obj.children = []
// 	domtree.children.forEach(item => obj.children.push(dom2Json(item)))

// 	return obj
// }


// 19、实现JSON格式数据转dom


// function _render(vnode) {
// 	if(typeof vnode === 'number') vnode = String(vnode)
// 	if(typeof vnode === 'string') return document.createTextNode(vnode)
// 	const dom = document.createElement(vnode.tag)
// 	if(vnode.attrs) {
// 		let keys = Object.keys(vnode.attrs)
// 		keys.forEach(key => dom.setAttribute(key, vnode.attrs[key]))
		
// 	}
// 	if(vnode.children && Array.isArray(vnode.children)) {
// 		vnode.children.forEach(item => dom.appendChild(_render(item)))
// 	}
// 	return dom
// }


// 20、实现模板字符串解析

// let template = "我是{{name}}，年龄{{age}}，性别{{sex}}";
// let data = {
//   name: "张三",
//   age: 18,
// 	sex: '男'
// };

// function render(template, data) {
// 	const computed = template.replace(/\{\{(\w+)\}\}/g, function (match, key) {
// 		return data[key]
// 	})

// 	return computed
// }
// console.log(render(template, data))


// 21、实现对象的扁平化

// const isObject = (obj) => typeof obj === 'object' && obj !== null

// const isArray = (arr) => Array.isArray(arr)

// function flatten(obj) {
// 	let newObj = {}
// 	const fn = (value, str) => {
// 		if(!isObject(value)) {
// 			let newStr = str + ''
// 			newObj[newStr] = value
// 			return
// 		}
// 		for(let key in value) {
// 			if(isArray(value)) {
// 				fn(value[key], str + `[${key}]`)
// 			}else {
// 				fn(value[key], str === '' ? str + `${key}` : str + `.${key}`)
// 			}
// 		}
		
// 	}
// 	fn(obj, '')
// 	return newObj
// }
// const obj = {
// 	a: {
// 			b: 1,
// 			c: 2,
// 			d: {e: 5}
// 	},
// 	b: [1, 3, {a: 2, b: 3}],
// 	c: 3
//  }
//  console.log(flatten(obj))

// 22、列表转成树形结构

// function listToTree(data) {
// 	let map = {}
// 	let tree = []
// 	data.forEach(item => map[item.id] = item)
// 	data.forEach(item => {
// 		if(map[item.parentId]) {
// 			(map[item.parentId].children || (map[item.parentId].children = [])).push(item)
// 		}else {
// 			tree.push(item)
// 		}
// 	})

// 	return tree
// }

// let arr = [
// 	{
// 			id: 1,
// 			text: '节点1',
// 			parentId: 0 //这里用0表示为顶级节点
// 	},
// 	{
// 			id: 2,
// 			text: '节点1_1',
// 			parentId: 1 //通过这个字段来确定子父级
// 	}
// ]
// console.log(listToTree(arr))

// 23、树形结构转成列表

// function treeToList(data) {
// 	let arr = []

// 	const fn = (tree) => {
// 		tree.forEach(item => {
// 			arr.push(item)
// 			if(item.children) {
// 				fn(item.children)
// 				delete item.children
// 			}
// 		})
// 	}

// 	fn(treeData)
// 	return arr
// }
// let treeData = [
// 	{
// 			id: 1,
// 			text: '节点1',
// 			parentId: 0,
// 			children: [
// 					{
// 							id:2,
// 							text: '节点1_1',
// 							parentId:1
// 					}
// 			]
// 	}
// ]
// console.log(treeToList(treeData))

// 24、大数相加

// function add(a, b) {
// 	let maxLength = Math.max(a.length, b.length)
// 	let t = 0
// 	let f = 0
// 	let sum = ''
// 	a = a.padStart(maxLength, 0)
// 	b = b.padStart(maxLength, 0)
// 	for(let i = maxLength - 1; i >= 0; i--) {
// 		t = parseInt(a[i]) + parseInt(b[i]) + f
// 		f = Math.floor(t / 10)
// 		sum = (t % 10) + sum
// 	}
// 	if(f !== 0) {
// 		sum = '' + f + sum
// 	}
// 	return sum
// }
// let a = "9007199254740991"
// let b = "1234567899999999999"

// console.log(add(a, b))

// 25、isCyclic 判断循环引用

// const isObject = (obj) => typeof obj === 'object' && obj !== null

// function isCyclic(obj) {
// 	let arr = [obj]
// 	let flag = false
// 	const dfs = (newObj) => {
// 		if(!isObject(newObj)) return 
// 		for(let key in newObj) {
// 			if(arr.includes(newObjp)) {
// 				flag = true
// 				return
// 			}
// 			if(isObject(newObj[key])) {
// 				arr.push(newObj[key])
// 			}
// 			dfs(newObj[key])
// 		}
// 	}

// 	return flag
// }


// 26、实现Object.create

// function mpyPCreate(prop, props) {
// 	if(['object', 'function'].includes(typeof prop)) {
// 		throw Error('参入参数不正确')
// 	}

// 	function Fn() {}
// 	Fn.prototype = prop
// 	const obj = new Fn()
// 	if(props) {
// 		Object.defineProperties(obj, props)
// 	}

// 	if(prop === null) {
// 		obj.__proto__ = null
// 	}
// 	return obj
// }


// 27、两数交集

// function intersect(num1, num2) {
// 	const len1 = num1.length
// 	const len2 = num2.length
// 	num1.sort((a, b) => a - b)
// 	num2.sort((a, b) => a - b)
// 	let res = []
// 	let i = 0
// 	let j = 0
// 	while(i < len1 && j < len2) {
// 		if(num1[i] === num2[j]) {
// 			res.push(num1[i])
// 			i++
// 			j++
// 		}else if(num1[i] < num2[j]) {
// 			i++
// 		}else {
// 			j++
// 		}
// 	}
// 	return res
// }
// let m1 = [4, 9, 5]
// let m2 = [9, 4, 9, 8, 4]
// let n1 = [1, 2, 2, 1]
// let n2 = [2, 2]
// console.log(intersect(m1, m2))
// console.log(intersect(n1, n2))

// 28、

// var myAtoi = function(s) {
// 	let str = ''
// 	let flag = ''
// 	let flagArr = ['-', '+']
// 	let len = s.length
// 	let reg = /[0-9]/
	
// 	for(let i= 0; i < len; i++) {
// 			if(s[i] === ' ') {
// 				continue
// 			}
// 			if(flagArr.includes(s[i])) {
// 				if(flag) return 0 
// 				// let newStr = s.substring(0, i)
// 				// 	if(new) {}
// 					flag = s[i]
// 					continue
// 			}
// 			if(reg.test(s[i])) {
					
// 					str = str + (str === '' && s[i] == '0' ? '' : s[i])
// 			}else {
// 					break
// 			}
// 	}
// 	let num = flag === '-' ? str * (-1) : str * 1
// 	if(num > 2147483647) {
// 			return 2147483647
// 	}else if(num < -2147483648) {
// 			return -2147483648
// 	}else {
// 			return num
// 	}
// };

// var threeSum = function(nums) {
// 	if(!nums.length) return []
// 	nums.sort((a, b) => a - b)
// 	let len = nums.length
// 	let result = []
// 	for(let i = 0; i < len; i++) {
// 			let first = nums[i]
// 			let target = -[first]
// 			if(i > 0 && nums[i] === nums[i - 1]) {
// 					continue
// 			}
// 			let left = i + 1
// 			let right = len
// 			while(left < right) {
// 					if(nums[left] + nums[right] === target) {
// 							result.push([nums[left], nums[right], first])
// 							left++
// 							right--
// 							while(nums[left] === nums[left - 1]) {
// 									left++
// 							}
// 							while(nums[right] === nums[right + 1]) {
// 									right--
// 							}
// 					}else if(nums[left] + nums[right] < target){
// 							left++
// 					}else {
// 							right--
// 					}
// 			}
// 	}
// 	return result
// };


// var maxProfit = function(prices) {
// 	if(!prices.length) return 0
// 	let len = prices.length
// 	let max = 0
// 	let leftVal = prices[0]
// 	for(let i = 1; i < len; i++) {
// 			if(leftVal < prices[i]) {
// 					max = Math.max(prices[i] - leftVal, max)
// 			}else {
// 					leftVal = prices[i]
// 			}
// 	}
// 	return max
// };


// var moveZeroes = function(nums) {
// 	if(!nums.length) return []
// 	let len = nums.length
// 	let arr = []
// 	for(let i = 0; i < len; i++) {
// 			if(nums[i] === 0) {
					
// 			}
// 	}
// 	let len1 = arr.length
// 	for(let i = 0; i < len1; i++) {
// 			nums.splice(arr[i], 1)
// 			nums.push(0)
// 	}
// 	return nums
// };

// console.log(moveZeroes([0,1,0,3,12]))


// var merge = function(nums1, m, nums2, n) {
// 	let arr1 = nums1.splice(0, m)
// 	let arr2 = nums2.splice(0, n)
// 	return [...arr1, ...arr2].sort((a, b) => a - b)
// };

// console.log(merge([1,2,3,0,0,0], 3, [2,5,6], 3))


// var subsets = function(nums) {
// 	if(!nums.length) return []
// 	let len = nums.length
// 	let res = [[]]
// 	const dfs = (i, str) => {
// 			for(let j = i; j < len; j++) {
// 					let newStr = str + ',' + nums[j]
// 					res.push(newStr.split(',').map(item => Number(item)))
// 					dfs(j+1, newStr)
// 			}
// 	}
// 	for(let i = 0; i < len; i++) {
// 			res.push([nums[i]])
// 			dfs(i+1, '' + nums[i])
// 	}
// 	return res
// };

// console.log(subsets([1,2,3]))


// function csm (str1, str2) {
// 	let l1 = str1.length;
// 	let l2 = str2.length;
// 	let strArr1 = str1.split('');
// 	let strArr2 = str2.split('');
// 	let ma = [];
// 	let max = 0;
// 	for (let i = 0; i < l1; i++) {
// 		let sa = [];
// 		for (let j = 0; j < l2; j++) {
// 			sa[j] = 0;
// 		}
// 		ma.push(sa);
// 	}

// 	for (let m = 0; m < l1; m++) {
// 		for (let n = 0; n < l2; n++) {
// 		    if (strArr1[m] === strArr2[n]) {
// 		        //处理边界
// 				if (m == 0 || n == 0) {
// 					ma[m][n] = 1;
// 				} else {
// 					ma[m][n] = ma[m - 1][n - 1] + 1;
// 				}
// 				max = Math.max(max, ma[m][n]);
// 			}
// 		}
// 	}
// 	return max;
// }

// console.log(csm("abcde", "ace"))

let obj = {
	n: 1,
	add: function() {
		console.log(this)
		this.n++
	}
}

let {n, add} = obj

add()

console.log(obj.n)